/**
 * @fileoverview Dom，操作dom
 * Created by 2kid.
 * Date: 11-11-4
 * Time: 上午10:33
 * @author 2kid
 * @version 0.001
 */


(function () {
    var win = window, doc = win['document'], docElement = doc.documentElement;
    //将Dom类放在Fky命名空间下
    /**
     * @name F.Dom
     * @namespace Fky.Dom or F.Dom   dom模块，需要core模块
     */
    var dom = Dom;
    win['Fky']['Dom'] = dom;

    var f = win['Fky'];
    //创建Dom类
    /**
     * @function
     * @constructor
     * @param seletor
     */
    function Dom(seletor) {
        this.elem = [];
        if (f.type(seletor, 'string')) {
            this.elem = dom.query(f.trim(seletor));


        } else if (f.type(seletor, 'array')) {
            this.elem = seletor;
        } else if (dom.isdom(seletor)) {
            this.elem = seletor.get();
        }

        //添加数组访问形式
        //for ie6,7
        this.length = 0;
        Array.prototype.push.apply(this, this.elem);
    }

    f.extend(dom, {
        NodeType:{ELEMENT_NODE:1, ATTRIBUTE_NODE:2, TEXT_NODE:3, COMMENT_NODE:8, DOCUMENT_NODE:9}
    }, true);

    /**
     *  dom 查询，遍历，过滤
     */
    f.extend(dom, {

        /**
         * @name F.Dom.prototype.find
         * @function
         * @description css 选择器 默认支持 #abc,#a div,div.a,.c ,在支持querySelectorAll，可支持所有的css选择器
         * @param seletor
         * @return {Object} dom
         */
        find:function (seletor) {
            return  new dom(f.merge([], dom.select.query(seletor, this.elem)));
        },
        /**
         * @name F.Dom.prototype.eq
         * @function
         * @description 返回索引元素的对象
         * @param {Number} i  从0开始，返回索引元素的dom对象
         * @return {Object} dom
         */
        eq:function (i) {
            if (f.type(i, 'number')) {
                return new dom([this.elem[i]]);
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.slice
         * @function
         * @description 获取包含当前节点列表选定范围内原生节点的 dom 对象
         * @param {Number} start  范围开始位置
         * @param {Number} end  范围结束位置, 忽略的话结束坐标为当前列表末尾
         * @return {Object} dom
         */
        slice:function (start, end) {
            return new dom(Array.prototype.slice.apply(this, arguments));
        },
        /**
         * @name F.Dom.prototype.each
         * @function
         * @description 循环每个元素
         * @param fn (item,i)  函数中的this指向每个元素对应的f.dom对象，item元素，i对应索引
         * @return {Object} dom
         */
        each:function (fn) {
            var thatelem = this.elem;
            f.each(this.elem, function (item, i) {
                //使调用函数的this为当前元素的dom对象
                this.elem = [item];
                fn.call(this, item, i);
            }, this);
            this.elem = thatelem;
            return this;
        },
        /**
         * @name F.Dom.prototype.filter
         * @function
         * @description 过滤已选择的元素
         * @param {String | Function } expr    String过滤表达式|Function自定义过滤函数
         * @return {Object} dom
         */
        filter:function (expr) {
            var elem = [], thatelem = this.elem;
            if (f.type(expr, 'string')) {
                elem = dom.filter.exec(expr, this.elem);
            } else if (f.type(expr, 'function')) {
                this.elem = f.filter(this.elem, function (item, i) {
                    elem = [item];
                    return expr.call(this, item, i);
                }, this);
            }
            this.elem = thatelem;
            return new dom(f.merge([], elem));

        },
        /**
         * @name F.Dom.prototype.next
         * @function
         * @description 后一个同辈元素
         * @return {Object} dom
         */
        next:function () {
            return this._wraker('nextSibling', false);
        },
        /**
         * @name F.Dom.prototype.nextAll
         * @function
         * @description 所有在当前元素后面同辈元素
         * @return {Object} dom
         */
        nextAll:function () {
            return this._wraker('nextSibling', true);
        },
        /**
         * @name F.Dom.prototype.prev
         * @function
         * @description 前一个同辈元素
         * @return {Object} dom
         */
        prev:function () {
            return this._wraker('previousSibling', false);
        },
        /**
         * @name F.Dom.prototype.prevAll
         * @function
         * @description 所有在当前元素前面同辈元素
         * @return {Object} dom
         */
        prevAll:function () {
            return this._wraker('previousSibling', true);
        },
        /**
         * @name F.Dom.prototype.children
         * @function
         * @description 当前元素的子元素
         * @return {Object} dom
         */
        children:function () {
            var tmpdom, thatelem = this.elem;
            this.elem = [];
            f.each(thatelem, function (ele) {
                this.elem.push(ele.firstChild);
            }, this);
            tmpdom = this._wraker('nextSibling', true);
            this.elem = thatelem;
            return tmpdom;
        },
        /**
         * @name F.Dom.prototype.parent
         * @function
         * @description 当前元素的父元素
         * @return {Object} dom
         */
        parent:function () {
            var elem = [];
            f.each(this.elem, function (ele) {
                if (f.inarray(elem, ele.parentNode) === -1) {
                    elem.push(ele.parentNode);
                }
            }, this);
            return new dom(elem);
        },
        /**
         *@function
         * @param dir
         * @param {Boolean} unlimit 无限制 true无限
         */
        _wraker:function (dir, unlimit) {
            var elem = [], thatelem = this.elem;

            f.each(thatelem, function (ele) {
                do {
                    if (ele && ele.nodeType === dom.NodeType.ELEMENT_NODE) {
                        elem.push(ele);
                    }
                    ele = ele[dir];
                } while (ele && (unlimit || ele.nodeType !== dom.NodeType.ELEMENT_NODE));
            });
            return new dom(elem);
        }

    });
    /**
     * 操作元素属性，样式，val，text，html
     */
    f.extend(dom, {
        /**
         * @name F.Dom.prototype.attr
         * @function
         * @description 设置或获取属性，不能设置class属性请用addclass，style属性请用css，不能设置on...等事件
         * @param {String | Object} name  String如果第二个参数设置了，则设置属性，否则获取第一个元素的属性 |
         *                                 Object设置多个属性
         * @param {String} value
         * @return {Object | string}
         */
        attr:function (name, value) {
            function set(ele, k, v) {
                if (k in ele) {
                    ele[k] = v;
                } else {
                    ele.setAttribute(k, v);
                }
            }

            function get(ele, k) {
                if (k in ele) {
                    return ele[k];
                }
                return ele.getAttribute(k, 2)
            }

            if (f.type(name, 'string')) {
                if (!f.type(value, 'undefined')) {
                    f.each(this.elem, function (ele) {
                        set(ele, name, value);
                    }, this);
                } else {
                    if (this.elem.length > 0) {
                        return get(this.elem[0], name);
                    }
                }
            } else if (f.type(name, 'object')) {
                f.each(this.elem, function (ele) {
                    f.each(name, function (v, k) {
                        set(ele, k, v);
                    }, this);
                }, this);
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.hasClass
         * @function
         * @description 是否有class
         * @param name classname
         * @return {Boolean}
         */
        hasClass:function (name) {
            if (f.type(name, 'string')) {
                f.each(this.elem, function (ele) {
                    var oldclassarr = ele.className.match(/\S+/g) || [];
                    if (f.inarray(oldclassarr, name)) {
                        return true;
                    }
                }, this);
            }
            return false;
        },
        /**
         * @name F.Dom.prototype.addclass
         * @function
         * @description 添加class
         * @param {String } name  类名，可添加多个，中间使用空格
         * @return {Object} dom
         */
        addclass:function (name) {
            if (f.type(name, 'string')) {
                f.each(this.elem, function (ele) {
                    var oldclass = ele.className, oldclassarr = oldclass.match(/\S+/g) || [];
                    f.each(name.match(/\S+/g), function (nclass) {
                        if (f.inarray(oldclassarr, nclass) === -1) {
                            oldclass += ' ' + nclass;
                        }
                    }, this);
                    ele.className = oldclass;
                }, this);
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.removeclass
         * @function
         * @description 删除class
         * @param {String } name  类名，可选，可删除多个，中间使用空格，不传值，则删除所有的classname
         * @return {Object} dom
         */
        removeclass:function (name) {
            if (f.type(name, 'string')) {
                f.each(this.elem, function (ele) {
                    var oldclass = ele.className, oldclassarr = oldclass.match(/\S+/g) || [];
                    //遍历每个class
                    f.each(name.match(/\S+/g), function (nclass) {
                        var i = f.inarray(oldclassarr, nclass);
                        if (i > -1) {
                            oldclassarr.splice(i, 1);
                        }
                    }, this);
                    ele.className = oldclassarr.join(' ');
                }, this);
            } else {
                f.each(this.elem, function (ele) {
                    ele.className = '';
                });

            }
            return this;
        },
        /**
         * @name F.Dom.prototype.css
         * @function
         * @description 设置或获取css样式
         * @param {String | Object} name  String如果第二个参数设置了，则设置样式，
         *                  否则获取第一个元素样式,  |
         *                                 Object设置多个样式，
         * @param {String} value 可选 第二个参数必须为字符串，对于宽度等这样的样式，请加单位，如 '200px'
         * @return {Object | string}
         */
        css:function () {
            var TOLINE = 1, TOCASE = 2;
            var BORDER = {
                thin:['1px', '2px'],
                medium:['3px', '4px'],
                thick:['5px', '6px']
            };

            function swh(str, mode) {
                switch (mode) {
                    case TOLINE:
                    {
                        str = str.replace(/([A-Z])/g, function (s) {
                            s = '-' + s.toLowerCase();
                            return s;
                        });
                        break;
                    }
                    case TOCASE:
                    {
                        str = str.replace(/-\w/g, function (s) {
                            s = s.substring(1).toUpperCase();
                            return s;
                        });
                        break;
                    }
                }
                return str;
            }

            function convertPixelValue(el, value) {
                var style = el.style,
                    left = style.left,
                    rsLeft = el.runtimeStyle.left,
                    px;
                el.runtimeStyle.left = el.currentStyle.left;
                style.left = value || 0;
                px = style.pixelLeft;
                style.left = left;//还原数据
                el.runtimeStyle.left = rsLeft;//还原数据
                return px + "px"
            }

            function rgbTOhsl(rgb) {
                if (rgb.indexOf('#') > -1) return rgb;
                var s = '#', colorArr = rgb.match(/\d+/g),
                    r = colorArr[0], g = colorArr[1], b = colorArr[2];
                s += parseInt(r, 10) < 16 ? '0' + parseInt(r, 10).toString(16) : parseInt(r, 10).toString(16);
                s += parseInt(g, 10) < 16 ? '0' + parseInt(g, 10).toString(16) : parseInt(g, 10).toString(16);
                s += parseInt(b, 10) < 16 ? '0' + parseInt(b, 10).toString(16) : parseInt(b, 10).toString(16);
                return s;
            }

            function converborder(key, val, ele) {
                var s = key.replace('Width', 'Style');
                //borderstyle：none
                if (val === 'medium' && get(ele, s) === 'none') {
                    return '0px';
                }
                return !!win.XDomainRequest ? BORDER[val][0] : BORDER[val][1];
            }

            function set(ele, key, value) {
                if (!win.getComputedStyle) {
                    if (key === 'opacity') {
                        //filter: alpha(opacity = 50);
                        key = 'filter';
                        value = 'alpha(opacity = ' + value * 100 + ') ';
                        ele.style.zoom = 1;
                    }
                    if (key === 'float') {
                        key = 'styleFloat';
                    }
                }
                ele.style[key] = value;
            }


            function get(ele, key) {
                var v = '';
                var oRect = ele.getBoundingClientRect();
                if (key === 'width') {

                    v = oRect.right - oRect.left -
                        parseFloat(get(ele, 'padding-left')) - parseFloat(get(ele, 'border-left-width')) -
                        parseFloat(get(ele, 'padding-right')) - parseFloat(get(ele, 'border-right-width')) + 'px';
                    return v;
                } else if (key === 'height') {
                    v = oRect.bottom - oRect.top -
                        parseFloat(get(ele, 'padding-top')) - parseFloat(get(ele, 'border-top-width')) -
                        parseFloat(get(ele, 'padding-bottom')) - parseFloat(get(ele, 'border-bottom-width')) + 'px';
                    return v;
                }

                if (win.getComputedStyle) {
                    key = swh(key, TOLINE);
                    v = win.getComputedStyle(ele, null).getPropertyValue(key);
                } else {

                    if (key === 'float') {
                        key = 'styleFloat';
                    }
                    if (key === 'opacity') {
                        key = 'filter';
                    }
                    key = swh(key, TOCASE);
                    //获取计算后的样式
                    v = ele.currentStyle[key];

                    //转换单位为px
                    if (/\d+(em|pt|mm|cm|pc|in|ex|rem|vw|vh|vm|ch|gr)$/.test(v)) {
                        v = key === 'fontSize' ? '1em' : v;
                        v = convertPixelValue(ele, v);

                    }


                    //转换border的thin medium thick
                    if (v in BORDER && /^(border).+(Width)$/.test(key)) {
                        v = converborder(key, v, ele);

                    }
                    if (key === 'filter') {
                        v = v ? v.match(/\d+/) / 100 : 1;
                    }
                }
                if (v === 'auto' && key !== 'overflow') {
                    v = 0 + 'px';
                }
                if (key === 'color') {
                    v = rgbTOhsl(v);
                }
                return v;
            }

            return function (name, value) {
                var elem = this.elem;
                if (f.type(name, 'string')) {
                    if (f.type(value, 'string')) {
                        f.each(elem, function (ele) {
                            set(ele, name, value);
                        }, this);

                    } else {
                        if (elem.length > 0) {
                            return get(elem[0], name);
                        }
                    }

                } else if (f.type(name, 'object')) {
                    f.each(elem, function (ele) {
                        f.each(name, function (v, k) {
                            set(ele, k, v);
                        }, this);
                    }, this);
                }
                return this;
            };
        }(),
        /**
         * @name F.Dom.prototype.val
         * @function
         * @description 设置或获取css样式         * 获取或设置表单元素的值。单选和复选框，下拉选择框最好设置value属性。要获取是否选中按钮，请用attr('checked')
         * @param v 可选，设置的值
         * @return {Object | string}
         */
        val:function (v) {
            var elem = this.elem, val = '';

            if (f.type(v, 'string')) {
                f.each(elem, function (ele) {
                    ele.value = v;
                });
            } else {
                var ele = elem[0], options = ele.options;
                //如果是多选返回数组
                if (ele.type !== 'select-one') {
                    var ret = [], i = 0, len = options.length;
                    for (; i < len; ++i) {
                        if (options[i].selected) {
                            ret.push(options[i].value);
                        }
                    }
                    val = ret;
                } else {
                    val = ele.value;
                }
                return val;
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.text
         * @function
         * @description 设置或获取元素的文本
         * @param v 可选，设置的值
         * @return {Object | string}
         */
        text:function (v) {
            var TEXT = 'innerText' in docElement ? 'innerText' : 'textContent';
            if (f.type(v, 'undefined')) {
                return this.elem[0][TEXT];
            } else {
                f.each(this.elem, function (ele) {
                    ele[TEXT] = v;
                });
            }
            return this;
        },
        /**
         * @name F.Dom.prototype.html
         * @function
         * @description 设置或获取元素html
         * @param v 可选，设置的值
         * @return {Object | string}
         */
        html:function (v) {
            if (f.type(v, 'undefined')) {
                return this.elem[0].innerHTML;
            } else {
                f.each(this.elem, function (ele) {
                    ele.innerHTML = v;
                });
            }
            return this;
        }
    });

    /**
     * 创建元素，静态方法
     */
    f.extend(dom, {
        /**
         * @name F.Dom.query
         * @function
         * @description css 选择器 默认支持 #abc,#a div,div.a,.c ,在支持querySelectorAll，可支持所有的css选择器
         * @param seletor css选择器字符串
         * @return { Array } 匹配的元素数组
         */
        query:function (seletor) {

            return  f.merge([], dom.select.query(f.trim(seletor)));
        },
        /**
         * @name F.Dom.create
         * @function
         * @description 创建元素，有两种形式，1.直接使用html格式，2.单个元素如 div。不能创建style，script,link
         * @param {String} html html格式字符串或标签名
         * @param {Object} attr 可选，当为标签名时，可以以键值对的形式添加属性，class属性请用className，
         *                      事件类型，如 onclick直接添加字符串， onclick='alert("")'
         * @return {Object} dom
         */
        create:function (html, attr) {
            var ELEM = /^[a-z]+$/,
                elem = [],
                ele,
                eletpl = '<%name %attr></%name>',
                div;

            //如果 单个元素，转换成innerHTML识别字符串 <div style="background:#ccc;"></div>
            if (ELEM.test(html.toLowerCase())) {
                eletpl = eletpl.replace(/%name/g, html);
                //如果添加了属性，替换成字符串  style='padding:10px;' src='http://i10.topit.me/l098/10098405313188eed9.jpg'
                if (f.type(attr, 'object')) {
                    var atr = '';
                    f.each(attr, function (v, k) {
                        if (k === 'className') {
                            k = 'class';
                        }
                        //替换 v中的双引号，避免和外面的冲突
                        v = v.replace(/"/g, '\'');
                        atr += k + '="' + v + '" ';

                    });
                    //添加属性
                    eletpl = eletpl.replace(/%attr/g, atr);

                    html = eletpl;
                }
            }
            div = doc.createElement('div');
            html = html.replace(/"/g, '\'');
            div.innerHTML = html;
            //获取html元素
            ele = div.firstChild;
            do {
                if (ele.nodeType === dom.NodeType.ELEMENT_NODE) {
                    elem.push(ele);
                }
            } while (ele = ele.nextSibling);

            div = null;

            return new dom(elem);
        },
        /**
         * @name F.Dom.isdom
         * @function
         * @description 判断是否为dom对象
         * @return {Boolean}
         */
        isdom:function (o) {
            return o instanceof dom;
        },
        /**
         * @name F.Dom.iswin
         * @function
         * @description 判断是否为window
         * @return {Boolean}
         */
        iswin:function (o) {
            return o === win;
        },
        /**
         * @name F.Dom.winsize
         * @function
         * @description 获取窗口宽高
         * @return {Object}  {w:xx,h:xx}
         */
        winsize:function () {
            var o = {}, docElemProp;
            docElemProp = docElement['clientWidth'];
            o.w = doc.compatMode === 'CSS1Compat' && docElemProp ||
                doc.body['clientWidth'] || docElemProp;
            docElemProp = docElement['clientHeight'];
            o.h = doc.compatMode === 'CSS1Compat' && docElemProp ||
                doc.body['clientHeight'] || docElemProp;
            return o;
        },
        /**
         * @name F.Dom.docsize
         * @function
         * @description 获取文档宽高
         * @return {Object}  {w:xx,h:xx}
         */
        docsize:function () {
            return{
                w:Math.max(
                    docElement['clientWidth'],
                    doc.body['scrollWidth'], docElement['scrollWidth']
                ),
                h:Math.max(
                    docElement['clientHeight'],
                    doc.body['scrollHeight'], docElement['scrollHeight']
                )
            };
        },
        /**
         * @name F.Dom.docscroll
         * @function
         * @description 获取或设置 文档滚动条位置 {l:xx,t:xx}
         * @return {Object}  {l:xx,t:xx}
         */
        docscroll:function (o) {
            if (f.type(o, 'undefined')) {
                return {
                    l:document.documentElement.scrollLeft || document.body.scrollLeft,
                    t:document.documentElement.scrollTop || document.body.scrollTop
                }
            } else {
                if ('l' in o) {
                    document.documentElement.scrollLeft = o.l;
                    document.body.scrollLeft = o.l;
                }
                if ('t' in o) {
                    document.documentElement.scrollTop = o.t;
                    document.body.scrollTop = o.t;
                }
            }

        }
    }, true);

    /**
     * 操作元素，移动，复制，删除
     */
    f.extend(dom, {
        /**
         * @name F.Dom.prototype.append
         * @function
         * @description  将参数添加到每个匹配元素内容的后面
         * @param html html格式字符串或F.Dom对象
         * @return {Object} F.Dom对象
         */
        append:function (html) {
            this._inject(html, function (ele, frag) {
                ele.appendChild(frag);
            });
            return this;
        },
        /**
         * @name F.Dom.prototype.prepend
         * @function
         * @description  将参数添加到每个匹配元素内容的前面
         * @param html html格式字符串或F.Dom对象
         * @return {Object} F.Dom对象
         */
        prepend:function (html) {
            this._inject(html, function (ele, frag) {
                ele.insertBefore(frag, ele.firstChild);
            });
            return this;
        },
        /**
         * @name F.Dom.prototype.before
         * @function
         * @description  将参数添加到每个匹配元素的前面
         * @param html html格式字符串或F.Dom对象
         * @return {Object} F.Dom对象
         */
        before:function (html) {
            this._inject(html, function (ele, frag) {
                ele.parentNode.insertBefore(frag, ele);
            });
            return this;
        },
        /**
         * @name F.Dom.prototype.after
         * @function
         * @description  将参数添加到每个匹配元素的后面
         * @param html html格式字符串或F.Dom对象
         * @return {Object} F.Dom对象
         */
        after:function (html) {
            this._inject(html, function (ele, frag) {
                ele.parentNode.insertBefore(frag, ele.nextSibling);
            });
            return this;
        },
        /**
         * @name F.Dom.prototype.remove
         * @function
         * @description  删除匹配的元素
         * @return {Object} F.Dom对象
         */
        remove:function () {
            f.each(this.elem, function (ele) {
                ele.parentNode.removeChild(ele);
            });
            return this;
        },
        /**
         * @name F.Dom.prototype.clone
         * @function
         * @description  拷贝匹配的元素
         * @return {Object} F.Dom对象
         */
        clone:function () {
            var elem = [];
            f.each(this.elem, function (ele) {
                elem.push(ele.cloneNode(true));
            });
            return new dom(elem);
        },
        _inject:function (html, fn) {
            var elem,
                frag = doc.createDocumentFragment();
            if (f.type(html, 'string')) {
                elem = dom.create(html).get();
            } else if (dom.isdom(html)) {
                elem = html.get();
            }
            f.each(elem, function (ele) {
                frag.appendChild(ele);
            });

            f.each(this.elem, function (ele) {
                fn(ele, frag.cloneNode(true));
            });
        }

    });
    /***
     * 获取元素宽，高，位置，滚动条位置
     *
     */
    f.extend(dom, {
        /**
         * @name F.Dom.prototype.width
         * @function
         * @description  获取元素宽度
         * @return { Number}
         */
        width:function () {
            var ele = this.elem[0];
            return this._size(ele, false, 'width');
        },
        /**
         * @name F.Dom.prototype.height
         * @function
         * @description  获取元素高度
         * @return { Number}
         */
        height:function () {
            var ele = this.elem[0];

            return this._size(this.elem[0], false, 'height');
        },
        /**
         * @name F.Dom.prototype.innerwidth
         * @function
         * @description  获取元素宽度，包含padding
         * @return { Number}
         */
        innerwidth:function () {
            return this._size(this.elem[0], 'inner', 'width');
        },
        /**
         * @name F.Dom.prototype.outerwidth
         * @function
         * @description  获取元素宽度，包含padding，border
         * @param {Boolean} includeMargin 是否包含margin
         * @return { Number}
         */
        outerwidth:function (includeMargin) {
            if (includeMargin === true) {
                return this._size(this.elem[0], true, 'width');
            } else {
                return this._size(this.elem[0], 'outer', 'width');
            }
        },
        /**
         * @name F.Dom.prototype.innerheight
         * @function
         * @description  获取元素高度，包含padding
         * @return { Number}
         */
        innerheight:function () {
            return this._size(this.elem[0], 'inner', 'height');
        },
        /**
         * @name F.Dom.prototype.outerheight
         * @function
         * @description  获取元素高度，包含padding，border
         * @param {Boolean} includeMargin 是否包含margin
         * @return { Number}
         */
        outerheight:function (includeMargin) {
            if (includeMargin === true) {
                return this._size(this.elem[0], true, 'height');
            } else {
                return this._size(this.elem[0], 'outer', 'height');
            }
        },
        _size:function (ele, p, d) {
            var dir = {'width':['left', 'right'], 'height':['top', 'bottom']};
            var oRect = ele.getBoundingClientRect(),
                tsize = oRect[dir[d][1]] - oRect[dir[d][0]];
            //outer*
            if (p === 'outer') {
                return  tsize;
            }
            //outer*(true)
            if (p === true) {
                return tsize + parseFloat(this.css('margin-' + dir[d][0])) + parseFloat(this.css('margin-' + dir[d][1]));
            }
            //inner*
            if (p === 'inner') {
                return tsize - parseFloat(this.css('border-' + dir[d][0] + '-' + d)) - parseFloat(this.css('border-' + dir[d][0] + '-' + d));
            }
            //width|height
            return parseFloat(this.css(d));

        },
        /**
         * @name F.Dom.prototype.offset
         * @function
         * @description  获取元素位置或设置元素位置，不传参数，则获取
         * @param {Boolean} relwin 可选，是否相对窗口，默认相对文档
         * @param {Object} o 设置元素位置{l:32,t:34}
         * @return {Object} dom对象或 {l:xx,t:xx}
         */
        offset:function (relwin, o) {
            var ele = this.elem[0],
                oRect = ele.getBoundingClientRect(),
                docscrll = dom.docscroll(),
                docl = relwin ? 0 : docscrll.l,
                doct = relwin ? 0 : docscrll.t,
                offset;
            if (f.type(o, 'object')) {
                this.each(function (el) {
                    var oldoffset = this.offset(relwin);
                    if (this.css('position') === 'static') {
                        this.css('position', 'relative');
                    }
                    if ('l' in o) {
                        el.style.left = parseFloat(this.css('left')) + o.l - oldoffset.l + 'px';
                    }
                    if ('t' in o) {
                        el.style.top = parseFloat(this.css('top')) + o.t - oldoffset.t + 'px';
                    }

                });
                return this;
            }

            if (typeof arguments.callee.offset != "number") {
                var temp = document.createElement("div");
                temp.style.cssText = "position:absolute;left:0;top:0;";
                document.body.appendChild(temp);
                arguments.callee.offset = -temp.getBoundingClientRect().top - docscrll.t;
                document.body.removeChild(temp);
                temp = null;
            }
            offset = arguments.callee.offset;
            return {
                l:oRect.left + offset + docl,
                t:oRect.top + offset + doct

            };

        },
        /**
         * @name F.Dom.prototype.scroll
         * @function
         * @description  获取或设置元素滚动条位置，不能获取文档的，文档的请直接使用 docscroll
         * @param {Object} o 可选，{ l:234,t:234}形式，可以只传一个。
         * @return {Object} dom对象或 {l:xx,t:xx}
         */
        scroll:function (o) {
            var ele = this.elem[0];
            if (f.type(o, 'undefined')) {
                return {
                    l:ele.scrollLeft,
                    t:ele.scrollTop
                }
            } else {
                if ('l' in o) {
                    ele.scrollLeft = o.l;
                }
                if ('t' in o) {
                    ele.scrollTop = o.t;
                }
            }
            return this;
        }
    });
    /**
     * 选择器
     */
    f.extend(dom, {


        /**
         * @name F.Dom.select
         * @object
         * @version 0.5
         * @description 选择器核心，可扩展。

         */
        select:{
            /**
             * @public
             * @param seletor
             * @param {Array}
                */
            query:function (seletor, stack) {
                var elem = [];
                //如果没有父元素
                stack = stack || [doc];
                if (stack.length > 0) {
                    // 使用querySelectorAll
                    if ('querySelectorAll' in stack[0]) {
                        f.each(stack, function (p) {
                            elem = f.merge(elem, p.querySelectorAll(seletor));
                        });
                    } else {
                        var selparse = this._selparse,
                            //选择器数组
                            selarr = seletor.match(/\S+/g);
                        //循环每个选择器集
                        for (var i = 0, ilen = selarr.length; i < ilen; i++) {
                            //匹配每个选择器

                            f.each(selparse, function (selreg, selkey) {
                                //selreg 已定义选择器匹配表达式
                                if (selreg.test(selarr[i])) {

                                    if (!stack[0]) return;

                                    //调用匹配选择器的函数
                                    elem = this._selquery[selkey].call(this, selarr[i], stack, selreg);
                                    stack = elem;

                                }
                            }, this);

                        }
                    }
                }


                return elem;
            },
            /***
             *
             * @name F.Dom.select.add
             * @function
             * @param parse 匹配选择器正则
             * @param fn(sel, stack, selreg) sel匹配选择器字符串，stack当前获取到的元素数组，selreg匹配选择器正则
             * @example
             * 示例，添加属性选择器
             *  第一个参数，，第二个对应调用的函数，
             F.Dom.select.add(/^([a-zA-Z]+)\[(.*)="(.*)"\]/,function(sel, stack, selreg){
             var elem = [],selarr = sel.match(selreg);
             F.each(stack, function(p) {
             elem = F.merge(elem, F.filter(p.getElementsByTagName(selarr[1]), function(ele) {
             if (!ele.getAttribute(selarr[2], 2)) return false;
             return F.trim(ele.getAttribute(selarr[2], 2)) === F.trim(selarr[3]);
             }));
             });
             return elem;
             });
             */
            add:function (parse, fn) {
                this._selparse.push(parse);
                this._selquery.push(fn);
            },
            _selparse:[
                /^[a-z]*#.+$/i,
                /^[a-z]+$/i,
                /^[a-z]*\..+/i
            ],
            _selquery:[
                function (sel, stack, selreg) {
                    //id 选择器
                    var elem = [], selarr = sel.split('#');
                    f.each(stack, function (p) {
                        var tmpelem = p.getElementById(selarr[1]);
                        if (selarr[0].length > 0) {
                            if (tmpelem.nodeName.toLowerCase() == selarr[0].toLowerCase()) {
                                elem.push(tmpelem);
                            }
                        } else {
                            elem.push(tmpelem);
                        }
                    });

                    return elem;
                }, function (sel, stack) {
                    //tag 选择器
                    var elem = [];
                    f.each(stack, function (p) {
                        elem = f.merge(elem, p.getElementsByTagName(sel));
                    });
                    return elem;
                },
                function (sel, stack) {
                    //class 选择器
                    var elem = [], selarr = sel.split('.'),
                        tag = selarr[0].length ? selarr[0] : '*';
                    f.each(stack, function (p) {
                        elem = f.merge(elem, f.filter(p.getElementsByTagName(tag), function (ele) {
                            if (!ele.className) return false;
                            return f.inarray(ele.className.match(/\S+/g), selarr[1]) > -1;
                        }));
                    });
                    return elem;
                }
            ]

        }
    }, true);
    /**
     * 过滤器
     */
    f.extend(dom, {
        /**
         * @name F.Dom.filter
         * @object
         * @version 0.5
         * @description 过滤器核心，可扩展，同选择器。
         * @example
         * 示例，属性选择器，在f.dom.select.filter 下添加过滤器匹配模式，在f.dom.filter 下添加对应的键值，
         * 默认提供
         fodd:/:odd/,
         feven:/:even/
         */
        filter:{

            exec:function (expr, stack) {
                var filparse = this._filparse;
                f.each(filparse, function (filreg, filkey) {
                    if (filreg.test(expr)) {
                        //调用对应过滤函数
                        stack = this._filflter[filkey].call(this, expr, stack, filreg);
                    }
                }, this);
                return stack;
            },
            /***
             *
             * @name F.Dom.filter.add
             * @function
             * @param parse 匹配过滤器正则
             * @param fn(expr, stack, filreg) expr匹配过滤器，stack当前获取到的元素数组，filreg匹配过滤器正则
             * @example
             * 示例，同选择器

             */
            add:function (parse, fn) {
                this._filparse.push(parse);
                this._filflter.push(fn);
            },
            _filparse:[
                /:odd/,
                /:even/
            ],
            _filflter:[
                function (expr, stack) {
                    return f.filter(stack, function (ele, i) {
                        return i % 2 !== 0;
                    }, this);
                },
                function (expr, stack) {
                    return f.filter(stack, function (ele, i) {
                        return i % 2 === 0;
                    }, this);
                }
            ]

        }
    }, true);
})();

/**
 * @name
 * 添加属性选择器
 */
F.Dom.select.add(/^([a-zA-Z]+)\[(.*)="(.*)"\]/, function (sel, stack, selreg) {
    var elem = [], selarr = sel.match(selreg);
    F.each(stack, function (p) {
        elem = F.merge(elem, F.filter(p.getElementsByTagName(selarr[1]), function (ele) {
            if (!ele.getAttribute(selarr[2], 2)) return false;
            return F.trim(ele.getAttribute(selarr[2], 2)) === F.trim(selarr[3]);
        }));
    });
    return elem;
});

